#include <math.h>
#include <stdio.h>
#include <string.h>
#include <argtable2.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/encoding.h>
#include <libxml/xmlwriter.h>
#if defined(LIBXML_WRITER_ENABLED) && defined(LIBXML_OUTPUT_ENABLED)
#define ENCODING "UTF-8"
#define oops(s) { perror((s)); exit(EXIT_FAILURE); }
#define MALLOC(s,t) if(((s) = malloc(t)) == NULL) { oops("error: malloc() "); }
	

	struct elem {
		int id;
		char *name;
		char *type;
		int length;
		int breadth;
	};
	struct adj {
		int t;
		int sedge;
		int edge;
		int distance;
	};
	struct adjw {
		int t;
		int distance;
	};
int arenax,arenay;
int **State;
char * outputfile;
char ** getcmdargs(int argc,char **argv);
int checker(int n,int id,int x,int y,int conf, struct elem ** Element,struct adjw ** AdjWallMatrix, struct adj ** AdjMatrix,int *Allocated, int ** Arena);
int allocator(int n,int id,int x,int y, struct elem ** Element,struct adjw ** AdjWallMatrix, struct adj ** AdjMatrix, int *Allocated, int ** Arena);
void xmlwriter(const char *uri,int **State,int n,struct elem ** Element);

int main(int argc, char **argv)
{
	xmlNode *curnode, *childnode, *grandchildnode;
	int i,j,ed,n=0;
	int rsum,imax,rmax=0;
	
	struct elem ** Element;
	struct adj ** AdjMatrix;
	struct adjw ** AdjWallMatrix;
	int **Arena;
	int * Allocated;
	xmlDocPtr doc;
	xmlNode *root =NULL;
	
	char ** infile=getcmdargs(argc,argv);
	if(infile[0]==NULL) return -1;
	printf("Input file: %s\n",infile[0]);
	/* Open the XML Document */
	
	doc = xmlParseFile(infile[0]);
	if (doc == NULL) printf("error: could not parse.");

	/*Get the root element*/
	root = xmlDocGetRootElement(doc);

	if(!root || !root->name || xmlStrcmp(root->name,(const xmlChar *) "list") )
	{
			xmlFreeDoc(doc);
			return 1;
	}

	/*Allocate enough space for the elements */
	for (curnode =root->children;curnode !=NULL; curnode=curnode->next) if(curnode->type == XML_ELEMENT_NODE && !xmlStrcmp(curnode->name,(const xmlChar *) "elem") ) n++; /* n=no. of elements */
	MALLOC(Element, sizeof(struct elem *) * n);
  	for (i = 0; i < n; i++) 
	{
    	MALLOC(Element[i], sizeof(struct elem));
  	}
	MALLOC(AdjMatrix, sizeof(struct adj *) * n);
  	for (i = 0; i < n; i++) 
	{
    	MALLOC(AdjMatrix[i], sizeof(struct adj) * n);
  	}
	MALLOC(AdjWallMatrix,sizeof(struct adjw *) * n);
   	for (i = 0; i < n; i++)
   	{
	    MALLOC(AdjWallMatrix[i], sizeof(struct adjw) * 4);
   	}
	MALLOC(State,sizeof(int *) *n);
	MALLOC(Allocated,sizeof(int) * n);
	for (i=0;i<n;i++)
	{
	MALLOC(State[i],sizeof(int)*6);
	}
	MALLOC(Arena,sizeof(int *)*arenax); /* Simple Two Dimenstional State Representation */
	   for (i = 0; i < arenax; i++)
   {
        MALLOC(Arena[i], sizeof(int)*arenay);
   }
	
	for(i=0;i<arenax;i++) for(j=0;j<arenay;j++) Arena[i][j]=0;
	for(i=0;i<n;i++) for(j=0;j<4;j++) AdjWallMatrix[i][j].t=0;
	for(i=0;i<n;i++) for(j=0;j<n;j++) AdjMatrix[i][j].t=0; /* Setting initial adjacency between elements to be nonexistant */

	/* For each children elem of the list */
	
	i=0; /*counter for element */
	for (curnode =root->children;curnode !=NULL; curnode=curnode->next)
	{
			if(curnode->type == XML_ELEMENT_NODE && !xmlStrcmp(curnode->name,(const xmlChar *) "elem") )
			{
				Element[i]=(struct elem *)malloc(sizeof(struct elem ));
				for(childnode=curnode->children; childnode!=NULL;childnode=childnode->next)
				{
					
					if(childnode->type == XML_ELEMENT_NODE && !xmlStrcmp(childnode->name,(const xmlChar *) "id"))
					{
					Element[i]->id = atoi((char *)xmlNodeGetContent(childnode));
					if(Element[i]->id >n) { printf("error: id out of range\n");exit(EXIT_FAILURE);}
					}
					if(childnode->type == XML_ELEMENT_NODE && !xmlStrcmp(childnode->name,(const xmlChar *) "name"))
					{
						Element[i]->name=(char *)xmlNodeGetContent(childnode);
					}
					if(childnode->type == XML_ELEMENT_NODE && !xmlStrcmp(childnode->name,(const xmlChar *) "type"))
               {
                                                Element[i]->type=(char *)xmlNodeGetContent(childnode);
					}
					if(childnode->type == XML_ELEMENT_NODE && ( !xmlStrcmp(childnode->name,(const xmlChar *) "ab") \
								|| !xmlStrcmp(childnode->name,(const xmlChar *) "bc") \
								|| !xmlStrcmp(childnode->name,(const xmlChar *) "cd") \
								|| !xmlStrcmp(childnode->name,(const xmlChar *) "da")))
					{
					for(grandchildnode=childnode->children; grandchildnode!=NULL;grandchildnode=grandchildnode->next)
						{
							if(grandchildnode->type == XML_ELEMENT_NODE && !xmlStrcmp(grandchildnode->name,(const xmlChar *) "length"))
							{
								if (!xmlStrcmp(childnode->name,(const xmlChar *) "ab")) { Element[i]->length=atoi((char *)xmlNodeGetContent(grandchildnode)); ed=0; }
								else if (!xmlStrcmp(childnode->name,(const xmlChar *) "bc")) { Element[i]->breadth=atoi((char *)xmlNodeGetContent(grandchildnode)); ed=1; }
								else if (!xmlStrcmp(childnode->name,(const xmlChar *) "cd") ) 
									{
									ed=2;
									if ( atoi((char *)xmlNodeGetContent(grandchildnode)) != Element[i]->length)
									{
									printf("error: Only rectangles allowed. Unequal opposite edges\n");
									exit(EXIT_FAILURE);
									}
									}
								else if (!xmlStrcmp(childnode->name,(const xmlChar *) "da") )
									{
									ed=3;
									if( atoi((char *)xmlNodeGetContent(grandchildnode)) != Element[i]->breadth)
									{
									printf("error: Only rectangles allowed. Unequal opposite edges\n");
									exit(EXIT_FAILURE);
									}
									}
								else { printf("error: Unknown edge %s \n",childnode->name); exit(EXIT_FAILURE);}
							}
							
							if(grandchildnode->type == XML_ELEMENT_NODE && !xmlStrcmp(grandchildnode->name,(const xmlChar *) "adjacence"))
							{
							int id=0,edge,ido;
							if (!xmlStrcmp(xmlGetProp(grandchildnode,(const xmlChar *)"edge"),(const xmlChar *)"w"))
							{
									  
									  ido=Element[i]->id;
									  AdjWallMatrix[ido-1][ed].t=1;
									  AdjWallMatrix[ido-1][ed].distance=atoi((char *)xmlGetProp(grandchildnode,(const xmlChar *)"distance"));
									  /*printf("%d,%d -> Wall\tDistance %d\n",ido,ed,AdjWallMatrix[ido-1][ed].distance);*/
							}
							else
								{
									  
							   if( ! (xmlGetProp(grandchildnode,(const xmlChar *)"id") && xmlGetProp(grandchildnode,(const xmlChar *)"edge") \
									&& xmlGetProp(grandchildnode,(const xmlChar *)"distance") ) ) 
									{ printf("error: Adjacency definition incomplete\n"); exit(EXIT_FAILURE);}
								else
									{
									/* ab=0 bc=1 cd=2 da=3 */
									if(!xmlStrcmp(xmlGetProp(grandchildnode,(const xmlChar *)"edge"),(const xmlChar *)"ab")) edge=0;
									else if(!xmlStrcmp(xmlGetProp(grandchildnode,(const xmlChar *)"edge"),(const xmlChar *)"bc")) edge=1;
									else if(!xmlStrcmp(xmlGetProp(grandchildnode,(const xmlChar *)"edge"),(const xmlChar *)"cd")) edge=2;
									else if(!xmlStrcmp(xmlGetProp(grandchildnode,(const xmlChar *)"edge"),(const xmlChar *)"da")) edge=3;
								
									id=atoi((char *)xmlGetProp(grandchildnode,(const xmlChar *)"id"));
									ido=Element[i]->id;
									if(id>n) { printf("error: id out of range\n");exit(EXIT_FAILURE);}
									AdjMatrix[ido-1][id-1].t=1;
									AdjMatrix[ido-1][id-1].sedge=ed;
									AdjMatrix[ido-1][id-1].edge=edge;
									AdjMatrix[ido-1][id-1].distance=atoi((char *)xmlGetProp(grandchildnode,(const xmlChar *)"distance"));
									/*printf("%d,%d -> %d,%d\tDistance %d\n",ido,AdjMatrix[ido-1][id-1].sedge,id,AdjMatrix[ido-1][id-1].edge,AdjMatrix[ido-1][id-1].distance);*/
									}
								}
							}
						}
					}
				}
			i++;
			}
	}
	n=i; /*Update n with the number of proper elements */
	
	/* Check the Adjacency Matrix for Errors and Other Matrix Transformations*/
	
	for(i=0;i<n;i++) if(AdjMatrix[i][i].t==1) { printf("error: Adjacency pointing to self\n"); exit(EXIT_FAILURE); } /* Adjacency with Self */
	
	for(i=0;i<n;i++) /* Adjacency condition mirroring if the xml file is not strict */
		{
		for(j=0;j<i;j++)
			{
			
			if (AdjMatrix[i][j].t != AdjMatrix[j][i].t && (AdjMatrix[j][i].t ==1 || AdjMatrix[i][j].t==1)) 
				{
				if (AdjMatrix[i][j].t ==1) { AdjMatrix[j][i].t=AdjMatrix[i][j].t;
							     AdjMatrix[j][i].sedge=AdjMatrix[i][j].edge;
							     AdjMatrix[j][i].edge=AdjMatrix[i][j].sedge;
							     AdjMatrix[j][i].distance = AdjMatrix[i][j].distance;}
				else { AdjMatrix[i][j].t=AdjMatrix[j][i].t;
							     AdjMatrix[i][j].sedge=AdjMatrix[j][i].edge;
							     AdjMatrix[i][j].edge=AdjMatrix[j][i].sedge;
							     AdjMatrix[i][j].distance = AdjMatrix[j][i].distance;}
				}
			}
		}
	/*for(i=0;i<n;i++) {for(j=0;j<n;j++) printf("%d\t",AdjMatrix[i][j].t); printf("\n");}*/
		
	for(i=0;i<n;i++) /* Inconsistent Data specified in the two adjacent elements */
		{
		for(j=0;j<i;j++)
			{
			if(AdjMatrix[i][j].t==1 && (AdjMatrix[i][j].t != AdjMatrix[j][i].t || AdjMatrix[i][j].edge != AdjMatrix[j][i].sedge \
			|| AdjMatrix[i][j].sedge != AdjMatrix[j][i].edge || AdjMatrix[i][j].distance != AdjMatrix[j][i].distance) ) 
				{ 
				printf("error: Adjacency incosistency\n");printf("%d %d\t (%d %d %d)\t (%d %d %d)\n",i+1,j+1,AdjMatrix[i][j].sedge,\
					AdjMatrix[i][j].edge,AdjMatrix[i][j].distance,AdjMatrix[j][i].sedge,AdjMatrix[j][i].edge,AdjMatrix[j][i].distance);exit(EXIT_FAILURE);
				}
			}
		}

	/* Find the Most Constrained Element */
	for(i=0;i<n;i++)
	{
		rsum=0;
		for(j=0;j<n;j++) rsum+=AdjMatrix[i][j].t;
		if(rsum>rmax)
		{ 
  		rmax=rsum;
		imax=i;
		}
	} /* imax = most constrained element */

	/* The Algo */
	for (i=0;i<n;i++) for(j=0;j<6;j++) State[i][j]=0;
	for (i=0;i<n;i++) Allocated[i]=-1;
		
	for (i=0;i<n;i++) allocator(n,i,0,0,Element,AdjWallMatrix,AdjMatrix,Allocated,Arena);

	xmlwriter(outputfile,State,n,Element); /* Write the state into XML file */


	/* Free the Document */
	xmlFreeDoc(doc);
	
	/* Free the global variables allocated by the parser */
	for (i = 0; i < n; i++) 
		{
  	  	free(Element[i]);
  		}
  	free(Element);
	xmlCleanupParser();
	printf("\n");
	return 0;
}

int checker(int n,int id,int x,int y,int conf,struct elem ** Element, struct adjw ** AdjWallMatrix, struct adj ** AdjMatrix,int *Allocated, int ** Arena)
{
		  int l,b,i,j,nalloc=0;
		  int ret=0;
		  int distw[4];
		  while(Allocated[nalloc]!=-1) nalloc++;
		  if(conf==0) { l=Element[id]->length;b=Element[id]->breadth;distw[0]=y;distw[1]=arenay-x-l;distw[2]=arenay-y-b;distw[3]=x; }
		  else if(conf==1) { l=-Element[id]->breadth;b=Element[id]->length;distw[0]=arenax-x;distw[1]=arenay-b-y;distw[2]=x-l;distw[3]=y;}
		  else if(conf==2) { l=Element[id]->length;b=-Element[id]->breadth;distw[0]=arenay-y;distw[1]=x-l;distw[2]=y-b;distw[3]=arenax-x;}
		  else if(conf==3) { l=-Element[id]->length;b=-Element[id]->breadth;distw[0]=x;distw[1]=y-l;distw[2]=arenax-x-b;distw[3]=arenay-y;}

		  if (x+l >arenax || y+b >arenay || x+l <0 ||y+b<0) return 0;
 		  for(i=0;i<4;i++)if(AdjWallMatrix[id][i].t==1 && AdjWallMatrix[id][i].distance!=distw[i]) return 0; /*Check Wall Adjacency */
		  for (i=x;i<x+l;i++) for(j=y;j<y+b;j++) if (Arena[i][j]==1) return 0;
		  /*Check Element Adjacency*/
		  ret=1;
		  for (i=0;i<n;i++) if (AdjMatrix[id][i].t==1 && State[i][5]==1)
		  {
		  		int lo,bo,xo,yo;
				int e1x1,e1x2,e1y1,e1y2,e2x1,e2x2,e2y1,e2y2;
		  
		  		 if (AdjMatrix[id][i].sedge==0) {e1x1=x;e1y1=y;e1x2=x+l;e1y2=y;}
		  		 else if (AdjMatrix[id][i].sedge==1) {e1x1=x+l;e1y1=y;e1x2=x+l;e1y2=y+b;}
		  		 else if (AdjMatrix[id][i].sedge==2) {e1x1=x;e1y1=y+b;e1x2=x+l;e1y2=y+b;}
		  		 else if (AdjMatrix[id][i].sedge==3) {e1x1=x;e1y1=y;e1x2=x;e1y2=y+b;}
				 		else { printf("Error: unknown edge %d\n",AdjMatrix[id][i].sedge);exit(EXIT_FAILURE); }
		  		 
		 		 if(State[i][4]==0) { lo=Element[i]->length;bo=Element[i]->breadth; }
		  		 else if(State[i][4]==1) { lo=-Element[id]->breadth;bo=Element[id]->length;}
	   		 else if(State[i][4]==2) { lo=Element[id]->length;bo=-Element[id]->breadth;}
		  		 else if(State[i][4]==3) { lo=-Element[id]->length;bo=-Element[id]->breadth;}
		  		 		else  {printf("Error: unknown configuration\n"); exit(EXIT_FAILURE); }

				 
				 xo=State[i][0];yo=State[i][1];
				 if (AdjMatrix[id][i].edge==0) {e2x1=xo;e2y1=yo;e2x2=xo+lo;e2y2=yo;}
		  		 else if (AdjMatrix[id][i].edge==1) {e2x1=xo+lo;e2y1=yo;e2x2=xo+lo;e2y2=yo+bo;}
		  		 else if (AdjMatrix[id][i].edge==2) {e2x1=xo;e2y1=yo+bo;e2x2=xo+lo;e2y2=yo+bo;}
		  		 else if (AdjMatrix[id][i].edge==3) {e2x1=xo;e2y1=yo;e2x2=xo;e2y2=yo+bo;}
				 		else { printf("Error: unknown edge\n");exit(EXIT_FAILURE); }

				 if((e1x1== e1x2 && e2y1==e2y2) || (e1y1==e1y2 && e2x1==e2x2)) {ret=0;return 0;}
		  		 else if (e1x1==e1x2 && e2x1==e2x2 && abs(e2x1-e1x1) == AdjMatrix[id][i].distance) ret=1;
				 else if (e1y1==e1y2 && e2y1==e2y2 && abs(e2y1-e1y1) == AdjMatrix[id][i].distance) ret=1;
				 else ret=0;

		  /*printf("For Element %d in conf(%d):\t Adjacency between (%d,%d)-(%d,%d) and (%d,%d)-(%d,%d) of Element %d in conf(%d)\n",id+1,conf,e1x1,e1y1,e1x2,e1y2,e2x1,e2y1,e2x2,e2y2,i+1,State[i][4]);*/
		  }
		  if(ret==1)
		  {
		  State[id][5]=1;
		  State[id][0]=x;State[id][1]=y;State[id][2]=x+l;State[id][3]=y+b;State[id][4]=conf;
		  Allocated[nalloc]=id;
		  /*printf("For Element %d:\t %d %d\tConf: %d\tNalloc: %d\n",id+1,x,y,conf,nalloc);*/
		  for (i=x;i<x+l;i++) for(j=y;j<y+b;j++)  Arena[i][j]=1;
		  printf(".");
		  return ret;
		  }
		  else {
			  printf(".");
			  return ret;
		  }
}

int allocator(int n,int id,int x,int y, struct elem ** Element,struct adjw ** AdjWallMatrix, struct adj ** AdjMatrix, int *Allocated, int ** Arena)
{
			int ret=0;
			int idx,nalloc=0;
loop:
		  	if (checker(n,id,x,y,State[id][4],Element,AdjWallMatrix,AdjMatrix,Allocated,Arena)) { ret=1;goto done; }
			else if (x==arenax && y==arenay && State[id][4]==3)
				{ 
						  printf ("Allocation not possible without backtracking: %d\t\n",id);
						  exit(EXIT_FAILURE);						  
						  /*nalloc=0;
						  while(Allocated[nalloc]!=-1) nalloc++;
						  idx=Allocated[nalloc];
						  printf("-------:D %d------------",nalloc);
						  Allocated[nalloc]=-1;
						  State[idx][5]=0;
						  if (allocator(n,idx,State[idx][0]+1,State[idx][1],Element,AdjWallMatrix,AdjMatrix,Allocated,Arena)==1) goto loop;
						  else {ret=0; goto done;}*/
				}
			else if (x==arenax && y==arenay) {x=0;y=0;State[id][4]+=1;}
			else if (x==arenax) {x=0;y++;}
			else x++;
			goto loop;
done:
			return ret;
}

void xmlwriter(const char *uri,int **State,int n,struct elem ** Element)
	{
	    int rc,i;
	    xmlTextWriterPtr writer;

   /* Create a new XmlWriter for uri, with no compression. */
    writer = xmlNewTextWriterFilename(uri, 0);
    if (writer == NULL) {
        printf("xmlwriter: Error creating the xml writer\n");
        return;
    }

    /* Start the document with the xml default for the version,
     * encoding UTF-8 and the default for the standalone
     * declaration. */
    rc = xmlTextWriterStartDocument(writer, NULL, ENCODING, NULL);
    if (rc < 0) {
        printf("xmlwriter: Error at xmlTextWriterStartDocument\n");
        return;
    }

	rc = xmlTextWriterStartElement(writer, BAD_CAST "space");
    	if (rc < 0) {
        		printf("xmlwriter: Error at xmlTextWriterStartElement\n");
		        return;
    			}
	rc = xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "x","%d",arenax);
		if (rc < 0) {
        			printf("xmlwriter: Error at xmlTextWriterWriteFormatAttribute\n");
        			return;
    				}
	rc = xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "y","%d",arenay);
		if (rc < 0) {
        			printf("xmlwriter: Error at xmlTextWriterWriteFormatAttribute\n");
        			return;
    				}
	for(i=0;i<n;i++)
	{
		rc = xmlTextWriterStartElement(writer, BAD_CAST "rect");
	    	if (rc < 0) {
        			printf("xmlwriter: Error at xmlTextWriterStartElement\n");
			        return;
    				}
		rc = xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "name","%s",Element[i]->name);
		if (rc < 0) {
        			printf("xmlwriter: Error at xmlTextWriterWriteFormatAttribute\n");
        			return;
    				}
		rc = xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "x1","%d",State[i][0]);
		if (rc < 0) {
        			printf("xmlwriter: Error at xmlTextWriterWriteFormatAttribute\n");
        			return;
    				}
		rc = xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "y1","%d",State[i][1]);
		if (rc < 0) {
        			printf("xmlwriter: Error at xmlTextWriterWriteFormatAttribute\n");
        			return;
    				}
		rc = xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "x2","%d",State[i][2]);
		if (rc < 0) {
        			printf("xmlwriter: Error at xmlTextWriterWriteFormatAttribute\n");
        			return;
    				}
		rc = xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "y2","%d",State[i][3]);
		if (rc < 0) {
        			printf("xmlwriter: Error at xmlTextWriterWriteFormatAttribute\n");
        			return;
    				}
		rc = xmlTextWriterEndElement(writer);
		if (rc < 0) {
	        		printf("xmlwriter: Error at xmlTextWriterEndElement\n");
			        return;
			        }
	}


	rc = xmlTextWriterEndDocument(writer);
    	if (rc < 0) {
		        printf("xmlwriter: Error at xmlTextWriterEndDocument\n");
       			return;
    			}
	xmlFreeTextWriter(writer);
	}

char ** getcmdargs(int argc, char **argv)
	{
	    struct arg_int  * x = arg_int0("x","spacex",NULL,              "define the length of the space (default is 1000)");
	    struct arg_int  * y  = arg_int0("y","spacey",NULL,              "define the length of the space (default is 700)");
	    struct arg_file * outfile = arg_file0("o",NULL,"<output>",           "output file (default is \"-\")");
	    struct arg_lit  * verbose = arg_lit0("v","verbose,debug",            "verbose messages");
	    struct arg_lit  * help    = arg_lit0(NULL,"help",                    "print this help and exit");
	    struct arg_lit  * version = arg_lit0(NULL,"version",                 "print version information and exit");
	    struct arg_file * infiles = arg_filen(NULL,NULL,NULL,1,argc+2,       "input file(s)");
	    struct arg_end  * end     = arg_end(20);
	    void* argtable[] = {x,y,outfile,verbose,help,version,infiles,end};
	    const char* progname = "oasp";
	    int nerrors;
	    int exitcode=0;
	    
	    if (arg_nullcheck(argtable) != 0)
        	{
	        /* NULL entries were detected, some allocations must have failed */
        	printf("%s: insufficient memory\n",progname);
	        exitcode=1;
        	goto exit;
        	}

	   x->ival[0]=1000;
	   y->ival[0]=700;
	   outfile->filename[0]="state.xml";

	   /* Parse the command line as defined by argtable[] */
	   nerrors = arg_parse(argc,argv,argtable);

	  /* special case: '--help' takes precedence over error reporting */
    		if (help->count > 0)
        		{
		        printf("Usage: %s", progname);
		        arg_print_syntax(stdout,argtable,"\n");
		        arg_print_glossary(stdout,argtable,"  %-25s %s\n");
		        exitcode=0;
		        goto exit;
		        }
	  /* special case: '--version' takes precedence error reporting */
		    if (version->count > 0)
		        {
		        printf("'%s' Open Architectural Space Programmer.\n",progname);
		        printf("August 2006, Dawn Thomas\n");
		        exitcode=0;
		        goto exit;
		        }


    /* If the parser returned any errors then display them and exit */
    if (nerrors > 0)
        {
        /* Display the error details contained in the arg_end struct.*/
        arg_print_errors(stdout,end,progname);
        printf("Try '%s --help' for more information.\n",progname);
        exitcode=1;
        goto exit;
        }

    /* special case: uname with no command line options induces brief help */
    if (argc==1)
        {
        printf("Try '%s --help' for more information.\n",progname);
        exitcode=0;
        goto exit;
        }
	arenax=x->ival[0];
	arenay=y->ival[0];
	outputfile=(char *)outfile->filename[0];
	printf("Output file: %s\n",outputfile);
	exit:
        arg_freetable(argtable,sizeof(argtable)/sizeof(argtable[0]));
	return (char **)infiles->filename;
	}
#endif
